﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;

namespace TS_XY_Train_Repaire.ToolSystem
{
    public partial class Tool_System_ToolBox_Form : DevExpress.XtraEditors.XtraForm
    {
        public Tool_System_ToolBox_Form()
        {
            InitializeComponent();
        }

        private void Tool_System_ToolBox_Form_Load(object sender, EventArgs e)
        {
            InitTreeList(tl_box);
            InitTreeList(tl_tool);

            tl_tool.OptionsDragAndDrop.AcceptOuterNodes = true;

            LoadData();
        }

        private void LoadData()
        {
            tl_box.DataSource = ToolDataMgr.GetInstance().GetToolListBoxAndTool();
            tl_tool.DataSource = ToolDataMgr.GetInstance().GetToolListNobox();

            tl_box.ExpandAll();
            tl_tool.ExpandAll();
        }

        void InitTreeList(TreeList treeList)
        {
            treeList.OptionsDragAndDrop.DragNodesMode = DragNodesMode.Multiple;
            treeList.OptionsDragAndDrop.AcceptOuterNodes = true;
            treeList.OptionsSelection.MultiSelect = true;
            treeList.CustomizeNewNodeFromOuterData += OnTLCustomizeNewNodeFromOuterData;
            treeList.BeforeDropNode += OnTLBeforeDropNode;
            treeList.BeforeDragNode += OnTLBeforeDragNode;
            treeList.AfterDropNode += OnTLAfterDropNode;
            treeList.DragOver += OnTLDragOver;
            treeList.DragDrop += OnTLDragDrop;
            treeList.DragLeave += OnTLDragLeave;
            treeList.GiveFeedback += OnTLGiveFeedback;
            treeList.CalcNodeDragImageIndex += OnTLCalcNodeDragImageIndex;
            treeList.ExpandAll();
        }

        void OnTLCalcNodeDragImageIndex(object sender, CalcNodeDragImageIndexEventArgs e)
        {
            DXDragEventArgs args = e.DragArgs.GetDXDragEventArgs(sender as TreeList);
            IDragNodesProvider provider = args.Data.GetData(typeof(IDragNodesProvider)) as IDragNodesProvider;
            if (provider == null) return;
            if (!AllowDropNodes(args, provider))
                e.ImageIndex = -1;
        }
        void OnTLGiveFeedback(object sender, GiveFeedbackEventArgs e)
        {
            e.UseDefaultCursors = false;
        }
        void OnTLDragLeave(object sender, EventArgs e)
        {
            SetDefaultCursor();
        }
        void OnTLDragDrop(object sender, DragEventArgs e)
        {
            SetDefaultCursor();
        }
        void OnTLDragOver(object sender, DragEventArgs e)
        {
            IDragNodesProvider provider = e.Data.GetData(typeof(IDragNodesProvider)) as IDragNodesProvider;
            if (provider == null)
            {
                e.Effect = DragDropEffects.None;
            }
            else
            {
                DXDragEventArgs args = e.GetDXDragEventArgs((TreeList)sender);
                e.Effect = GetDragDropEffect(args, provider);
            }
            SetDragCursor(e.Effect);
        }
        DragDropEffects GetDragDropEffect(DXDragEventArgs e, IDragNodesProvider provider)
        {
            return AllowDropNodes(e, provider) ? e.Effect : DragDropEffects.None;
        }
        bool AllowDropNodes(DXDragEventArgs e, IDragNodesProvider provider)
        {
            if (e.HitInfo.HitTest.RowInfo == null)
                return true;

            TreeListNode destNode = e.HitInfo.HitTest.RowInfo.Node;
            if (destNode == null)
                return true;

            if (e.DragInsertPosition == DragInsertPosition.None)
                return true;

            int destLevel = e.DragInsertPosition == DragInsertPosition.AsChild ? destNode.Level + 1 : destNode.Level;
            // 工具箱列表只允许插入到第一级（工具箱节点下）
            if (destNode.TreeList == tl_box && destLevel != 1)
                    return false;

            // 工具列表只允许插入到第一级
            if (destNode.TreeList == tl_tool && destLevel != 0)
                    return false;
         
            foreach (TreeListNode node in provider.DragNodes)
            {
                // 工具箱内不允许同一节点下移动
                if (destNode.TreeList == node.TreeList && destNode.ParentNode == node.ParentNode)
                {
                    return false;
                }

                // 工具箱第一级按钮不允许移动
                if (node.TreeList == tl_box && node.ParentNode == null)
                    return false;
            }
            return true;
        }
        TreeListNode HasAsParent(TreeListNode node1, TreeListNode node2)
        {
            if (node1.Level > node2.Level)
                return node1.HasAsParent(node2) ? node1 : null;
            if (node1.Level < node2.Level)
                return node2.HasAsParent(node1) ? node2 : null;
            return null;
        }
        void OnTLBeforeDragNode(object sender, BeforeDragNodeEventArgs e)
        {
            if (e.Nodes.Count <= 1) return;
            int i = 0, j = i + 1;
            List<TreeListNode> nonDragNodes = new List<TreeListNode>();
            while (i != e.Nodes.Count - 1)
            {
                TreeListNode nonDragNode = HasAsParent(e.Nodes[i], e.Nodes[j]);
                if (nonDragNode != null)
                    nonDragNodes.Add(nonDragNode);
                if (j == e.Nodes.Count - 1)
                {
                    i++;
                    j = i + 1;
                }
                else
                    j++;
            }
            if (nonDragNodes.Count == 0) return;
            foreach (TreeListNode node in nonDragNodes)
                e.Nodes.Remove(node);
        }

        bool AllowDropNode(TreeListNode sourceNode, TreeListNodes nodes)
        {
            foreach (TreeListNode node in nodes)
            {
                object value1 = sourceNode.GetValue("f_id");
                object value2 = node.GetValue("f_id");

                if (object.Equals(value1, value2))
                    return true;
            }
            return false;
        }
        void OnTLBeforeDropNode(object sender, BeforeDropNodeEventArgs e)
        {
            if (e.IsCopy) return;
            TreeListNodes nodes = e.DestinationNode == null ? ((TreeList)sender).Nodes : e.DestinationNode.Nodes;
            e.Cancel = AllowDropNode(e.SourceNode, nodes);

            if (!e.Cancel)
            {
                if (e.SourceNode.TreeList == tl_tool)
                {
                    // 移动到工具箱
                    int iToolID = int.Parse(e.SourceNode["f_id"].ToString());
                    int iParentID = int.Parse(e.DestinationNode["f_id"].ToString());
                    ToolDataMgr.GetInstance().ModifyToolParent(iToolID, iParentID);
                }
                else
                {
                    if (e.DestinationNode == null)
                    {
                        // 工具箱移到工具
                        int iToolID = int.Parse(e.SourceNode["f_id"].ToString());
                        ToolDataMgr.GetInstance().ModifyToolParent(iToolID, 0);
                    }
                    else
                    {
                        // 工具箱移到工具箱
                        int iToolID = int.Parse(e.SourceNode["f_id"].ToString());
                        int iParentID = int.Parse(e.DestinationNode["f_id"].ToString());
                        ToolDataMgr.GetInstance().ModifyToolParent(iToolID, iParentID);
                    }
                }

                LoadData();
            }
        }

        void OnTLAfterDropNode(object sender, AfterDropNodeEventArgs e)
        {
            LoadData();
        }

        void OnTLCustomizeNewNodeFromOuterData(object sender, CustomizeNewNodeFromOuterDataEventArgs e)
        {
            TreeList treeList = (TreeList)sender;
            e.NewData[treeList.ParentFieldName] = e.DestinationNode == null ? 0 : e.DestinationNode[treeList.KeyFieldName];
            e.NewData[treeList.KeyFieldName] = treeList.AllNodesCount;
            e.NewData[treeList.ImageIndexFieldName] = e.SourceNode[treeList.ImageIndexFieldName];
        }
  
        private void SetDefaultCursor()
        {
            Cursor = Cursors.Default;
        }
        private void SetDragCursor(DragDropEffects e)
        {
            if (e == DragDropEffects.Move)
                Cursor = Cursors.Default;
            //    Cursor = new Cursor(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("DevExpress.XtraTreeList.Demos.Images.move.ico"));
            //if (e == DragDropEffects.Copy)
            //    Cursor = new Cursor(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("DevExpress.XtraTreeList.Demos.Images.copy.ico"));
            if (e == DragDropEffects.None)
                Cursor = Cursors.No;  
        }

        
    }
}